Make GtkCssProvider deal with widget types not being in plain CamelCase
authorCarlos Garnacho <carlosg@gnome.org>
Wed, 19 Jan 2011 03:12:08 +0000 (04:12 +0100)
committerCarlos Garnacho <carlosg@gnome.org>
Wed, 19 Jan 2011 03:28:49 +0000 (04:28 +0100)
Fixes bug #BugĀ 639754, reported by Kjell Ahlstedt. gtkmm doesn't
use plain CamelCase for its widget type names, so in order to
distinguish widget type names from regions in the CSS parser,
the following checks are now done:

* if it contains an uppercase letter -> widget class (that should
  also work for gtkmm)

* if it's a string compound by lowercase letters and '-' -> it's
  a region, checks have been added in gtk_style_context_add_region()
  and gtk_widget_path_iter_add_region() to ensure this.

gtk/gtkcssprovider.c
gtk/gtkstylecontext.c
gtk/gtkstylecontext.h
gtk/gtkwidgetpath.c

index 89d549226b6a6fd351ee302b3885b438c40c0e5a..ea4530e9b49c0c2008568173c3dfaabbfe785a02 100644 (file)
@@ -1711,6 +1711,25 @@ parse_classes (SelectorPath   *path,
   selector_path_prepend_class (path, str);
 }
 
+static gboolean
+is_widget_class_name (const gchar *str)
+{
+  /* Do a pretty lax check here, not all
+   * widget class names contain only CamelCase
+   * (gtkmm widgets don't), but at least part of
+   * the name will be CamelCase, so check for
+   * the first uppercase char */
+  while (*str)
+    {
+      if (g_ascii_isupper (*str))
+        return TRUE;
+
+      str++;
+    }
+
+  return FALSE;
+}
+
 static GTokenType
 parse_selector (GtkCssProvider  *css_provider,
                 GScanner        *scanner,
@@ -1761,7 +1780,7 @@ parse_selector (GtkCssProvider  *css_provider,
                 parse_classes (path, pos + 1);
             }
         }
-      else if (g_ascii_isupper (scanner->value.v_identifier[0]))
+      else if (is_widget_class_name (scanner->value.v_identifier))
         {
           gchar *pos;
 
@@ -1802,7 +1821,7 @@ parse_selector (GtkCssProvider  *css_provider,
           else
             selector_path_prepend_type (path, scanner->value.v_identifier);
         }
-      else if (g_ascii_islower (scanner->value.v_identifier[0]))
+      else if (_gtk_style_context_check_region_name (scanner->value.v_identifier))
         {
           GtkRegionFlags flags = 0;
           gchar *region_name;
@@ -3313,8 +3332,7 @@ parse_rule (GtkCssProvider  *css_provider,
               return G_TOKEN_IDENTIFIER;
             }
         }
-      else if (prop[0] == '-' &&
-               g_ascii_isupper (prop[1]))
+      else if (prop[0] == '-')
         {
           GValue *val;
 
index e36bef4eb75fddd23c4b0285d84e36a3ede14786..0f30fcd3a17ee2398fc2d296eeb875bb7a7f5d4b 100644 (file)
@@ -2069,6 +2069,26 @@ gtk_style_context_list_regions (GtkStyleContext *context)
   return classes;
 }
 
+gboolean
+_gtk_style_context_check_region_name (const gchar *str)
+{
+  g_return_val_if_fail (str != NULL, FALSE);
+
+  if (!g_ascii_islower (str[0]))
+    return FALSE;
+
+  while (*str)
+    {
+      if (*str != '-' &&
+          !g_ascii_islower (*str))
+        return FALSE;
+
+      str++;
+    }
+
+  return TRUE;
+}
+
 /**
  * gtk_style_context_add_region:
  * @context: a #GtkStyleContext
@@ -2095,6 +2115,9 @@ gtk_style_context_list_regions (GtkStyleContext *context)
  *
  * would apply to even and odd rows, respectively.
  *
+ * <note><para>Region names must only contain lowercase letters
+ * and '-', starting always with a lowercase letter.</para></note>
+ *
  * Since: 3.0
  **/
 void
@@ -2109,6 +2132,7 @@ gtk_style_context_add_region (GtkStyleContext *context,
 
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
   g_return_if_fail (region_name != NULL);
+  g_return_if_fail (_gtk_style_context_check_region_name (region_name));
 
   priv = context->priv;
   region_quark = g_quark_from_string (region_name);
index a2ab473546b7a898cc8215e6bfdead12d01c436c..42eed4beee286bd1dd9a6183db608547ed747e1f 100644 (file)
@@ -595,6 +595,8 @@ const GValue * _gtk_style_context_peek_style_property (GtkStyleContext *context,
 void           _gtk_style_context_invalidate_animation_areas (GtkStyleContext *context);
 void           _gtk_style_context_coalesce_animation_areas   (GtkStyleContext *context,
                                                              GtkWidget       *widget);
+gboolean       _gtk_style_context_check_region_name   (const gchar     *str);
+
 
 void gtk_style_context_invalidate (GtkStyleContext *context);
 void gtk_style_context_reset_widgets (GdkScreen *screen);
index 6636abdd14c18ed58a643d24c18ec080d8cc761d..f0ae30ea146faea533b9450f3ed5d47afdce0f6d 100644 (file)
@@ -730,6 +730,9 @@ gtk_widget_path_iter_has_class (const GtkWidgetPath *path,
  * the hierarchy defined in @path. See
  * gtk_style_context_add_region().
  *
+ * <note><para>Region names must only contain lowercase letters
+ * and '-', starting always with a lowercase letter.</para></note>
+ *
  * Since: 3.0
  **/
 void
@@ -744,6 +747,7 @@ gtk_widget_path_iter_add_region (GtkWidgetPath  *path,
   g_return_if_fail (path != NULL);
   g_return_if_fail (path->elems->len != 0);
   g_return_if_fail (name != NULL);
+  g_return_if_fail (_gtk_style_context_check_region_name (name));
 
   if (pos < 0 || pos > path->elems->len)
     pos = path->elems->len - 1;